home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QuickTime - The Beta Release
/
QuickTime - The Beta Release.iso
/
Programming Stuff
/
Sample Code
/
MovieController Exerciser
/
BigEasy2.c
next >
Wrap
Text File
|
1991-08-13
|
35KB
|
1,747 lines
/*
File: BigEasy2.c
Copyright: © 1990 by Apple Computer, Inc., all rights reserved.
This file is used in these builds: Warhol
Change History (most recent first):
<26> 8/12/91 MD support for timing profiler nastiness
<25> 7/3/91 PH qd. is bad under old think
<24> 6/28/91 dvb Make it work with/without MacHeaders in LSC5.
<23> 6/4/91 PH compilin'
<22> 6/3/91 dvb Just hackin.
<21> 5/28/91 JB Added prototypes for BigEasy Proc Ptrs
<20> 5/27/91 PH to compile again...
<19> 5/25/91 JB OLD_THINK_C && TOOLBOX_LINKED
<18> 5/23/91 PH changes for THINK 5
<17> 5/22/91 PH new style prototypes
<16> 5/6/91 PH nifty line after about...
<15> 5/5/91 dvb Latest features, and App-Events for document open.
<14> 4/25/91 JB Changing to new THINK C interface files
<13> 4/19/91 PH i like content clicks
<12> 4/19/91 dvb Add WindowEventProc
<11> 3/29/91 PH minor activate fix
<10> 3/29/91 dvb Repair deactivate vs closewindow conflict, roll in latest cool
features.
<9> 3/9/91 dvb Adjust to work with or without (LSC) mac headers
<8> 3/7/91 JB Adjusting for using MacHeaders
<7> 3/1/91 dvb Trivial new functions
<6> 2/24/91 dvb Various cool new calls
<5> 2/18/91 dvb Miscellaneous Updates
<4> 1/9/91 JB Increasing ItemsPerMenu & #Menus
<3> 11/21/90 JB Changes for INIT & mpw compatability
<2> 11/17/90 dvb Pass on unused command-keys to document windows
<1> 11/17/90 dvb New again after 1st CD pressing! Yay!
To Do:
*/
/* file: BigEasy2.c
*
* Started 30 June 1988, more or less.
*
* A set of routines to allow the quick development
* of simple Macintosh applications.
*
*/
#define BigEasy2
#include <QuickDraw.h>
#include <GestaltEqu.h>
#include <Events.h>
#include <AppleEvents.h>
#include <Resources.h>
#include <Menus.h>
#include <ToolUtils.h>
#include <Menus.h>
#include <Windows.h>
#include <Dialogs.h>
#include <Memory.h>
#include <Desk.h>
#include <Fonts.h>
#include <OSEvents.h>
#include <SegLoad.h>
/* #define THINK_C_PROFILE /* */
#if defined(TIMING_PROFILE) || defined(STACK_KILLER)
#include "stack killer.h"
#endif
#include "BigEasy2.h"
/************************************
* Limits
************************************/
#define kMMax 10 /* Number of menus in menubar */
#define kMIMax 50 /* Number of items per menu */
#define kMenuNameMax 32 /* Length of a menu title */
#define kStagStepX 7
#define kStagStepY 7
#define kStagLimX 97
#define kStagLimY 37
/************************************
* Constants
************************************/
#define kOSEvent app4Evt /* event used by MultiFinder */
#define kSuspendResumeMessage 1 /* high byte of suspend/resume event message */
#define kResumeMask 1 /* bit of message field for resume vs. suspend */
#define kWinPosType 'bewP'
#define trapExitToShell 0xA9F4
/************************************
* Major BigEasy2 Structures
************************************/
typedef struct tEasyWindow
{
boolean wUsed;
long flags;
boolean wGrowable;
beUpdateProcPtr wUpdateProc;
beClickProcPtr wClickProc;
beKeyProcPtr wKeyProc;
beGoAwayProcPtr wGoAwayProc;
beZoomProcPtr wZoomProc;
beActivateProcPtr wActivateProc;
beDeactivateProcPtr wDeactivateProc;
beIdleProcPtr wIdleProc;
beResizeProcPtr wResizeProc;
beGrowWindowProcPtr wGrowWindowProc;
beEventProcPtr wEventProc;
WindowPtr wWindow;
} tEasyWindow;
typedef struct
{
short ref;
char mark;
char enable;
char cmdEquiv;
beMenuProcPtr proc;
} tEasyMenuItem;
/************************************
* Globals
************************************/
Rect gResizeLim = {50,50,1000,1000};
tEasyWindow **gEasyWindowListH; /* Handle to array of window objects */
tEasyWindow *gEasyWindowList; /* Pointer to array of window objects */
short gEasyWindowListSize; /* Number of window objects allocated */
/*** Menus ***/
MenuHandle gMenuHandleList[kMMax]; /* MenuHandles indexed by MenuID's */
short gMenuLength[kMMax];
char gMenuName[kMMax][kMenuNameMax];
tEasyMenuItem gMenu[kMMax][kMIMax];
short gMenuCount; /* How many menus defined */
short gCurrentMenu; /* the one to add to */
MenuHandle gMenuEdit; /* Which one is the edit menu? */
/*** Phantom Menu ***/
MenuHandle phantomMenuH = 0;
/*** About ***/
beAboutProcPtr gAboutProc;
char gAboutS0[256];
/*** Application Edit Commands ***/
beWNumCallProcPtr gAppUndoProc,gAppCutProc,gAppCopyProc,gAppPasteProc,gAppClearProc;
/*** Global Status ***/
beAboutProcPtr gMasterIdleProc;
short gStagX,gStagY;
WindowPtr gLastFrontIdle;
short gLastFrontWindowNumber;
short gSleep;
short gCoolDragState;
Point gCoolDragPoint;
WindowPtr gCoolDragWindow;
Boolean gInvalidMenuBar;
void *gOldExitToShell;
Boolean gHasAppleEvents;
/************************************
* Prototypes
************************************/
static void InitToolbox(void);
static void CheckMenubar(void);
static void EventLoop(void);
static void InitBigEasy(void);
static void InstallMyExitToShell(void);
static pascal void MyExitToShell(void);
static void GetGrowRect(WindowPtr,Rect*);
static void EnoughEasyWindows(short);
static void FrontDAEdits(void);
static tEasyWindow *GoodWNum(short);
static Boolean CoolBigEasyCmdKeys(short key);
static void DoMyAbout(void);
static void BEUndo(short);
static void BECopy(short);
static void BECut(short);
static void BEPaste(short);
static void BEClear(short);
static void BENull(void);
static void MenuClick(Point p);
static void DeleteIndexedMenuItem(short menu,short item);
static Boolean DoKeyPress(long k);
static void MenuPoint(long theclick);
static void StartMenus(void);
static short ScanWindowList(WindowPtr w);
static void DoMouseClick(EventRecord *event);
void MyDrawGrowIcon(WindowPtr w);
void main(void);
/************************************
* Some useful routines
************************************/
void InitToolbox(void)
{
#ifdef THINK_C
#if THINK_C < 5
InitGraf(&thePort);
#else
InitGraf(&qd.thePort);
#endif
#else
InitGraf(&qd.thePort);
#endif
InitFonts();
FlushEvents(0xffff,0);
InitWindows();
InitMenus();
InitDialogs(0);
TEInit();
InitCursor();
}
void GetGrowRect(WindowPtr w,Rect *r)
{
register Rect *gr;
gr = r;
*gr = w->portRect;
gr->left = gr->right - 15;
gr->top = gr->bottom - 15;
}
void GoWatch(void)
{
SetCursor(*(Cursor**)GetCursor(4));
}
void GoArrow(void)
{
#ifdef THINK_C
#if THINK_C < 5
SetCursor(&arrow);
#else
SetCursor(&qd.arrow);
#endif
#else
SetCursor(&qd.arrow);
#endif
}
void GoCursor(short c)
/*
* Attempt to set to cursor ID c,
* but skip it if not there.
*/
{
register Cursor **cur;
cur = (Cursor **)GetCursor(c);
if(cur)
SetCursor(*cur);
}
static void EnoughEasyWindows(short n)
/*
* If there are less than n window objects in the list,
* grow the handle appropriately.
*/
{
short i;
n++;
if(gEasyWindowListSize < n)
{
HUnlock((Handle)gEasyWindowListH);
SetHandleSize((Handle)gEasyWindowListH,sizeof(tEasyWindow) * (long)n);
HLock((Handle)gEasyWindowListH);
gEasyWindowList = *gEasyWindowListH;
for(i = gEasyWindowListSize; i < n; i++)
gEasyWindowList[i].wUsed = 0;
gEasyWindowListSize = n;
}
}
static tEasyWindow *GoodWNum(short n)
/*
* return true if n is the number of an
* existing, used window.
*/
{
register tEasyWindow *thisWindow;
if(n<0 || n>=gEasyWindowListSize)
return 0;
thisWindow = &gEasyWindowList[n];
if(thisWindow->wUsed)
return thisWindow;
else
return 0;
}
static void FrontDAEdits(void)
/*
* Check the front window. If it's a DA,
* enable all edit menu options.
*/
{
WindowRecord *w;
w = (WindowRecord*)FrontWindow();
if(w->windowKind < 0) /* Any click in a DA window: */
EnDisEdits(1,1,1,1,1); /* enable edit menu. */
}
void DoMyAbout(void)
{
DialogPtr d;
Handle h;
short hit;
if(gAboutProc)
(*gAboutProc)();
else
{
h = GetResource('DLOG',1962); /* does it exist? */
if( (ResError()==0) && (h!=nil) )
{
ParamText((StringPtr)gAboutS0,0,0,0);
d = GetNewDialog(1962,0,(WindowPtr)-1);
ModalDialog(nil,&hit);
DisposDialog(d);
}
}
}
void SetMasterIdle(r)
beAboutProcPtr r;
{
gMasterIdleProc = r;
}
void SetWindowResizeProc(short n,beResizeProcPtr resizeProc)
/*
* Sets the procedure which gets called when the window is resized
*/
{
tEasyWindow *thisWindow;
thisWindow = GoodWNum(n);
if(thisWindow)
thisWindow->wResizeProc = resizeProc;
}
void SetWindowGrowWindowProc(short n,beGrowWindowProcPtr growWindowProc)
/*
* Sets the procedure which gets called when the window grows.
* Allows alternate to GrowWindow.
*/
{
tEasyWindow *thisWindow;
thisWindow = GoodWNum(n);
if(thisWindow)
thisWindow->wGrowWindowProc = growWindowProc;
}
void SetWindowZoomProc(short n,beZoomProcPtr zoomProc)
{
register tEasyWindow *thisWindow;
thisWindow = GoodWNum(n);
if(thisWindow)
thisWindow->wZoomProc = zoomProc;
}
void SetWindowEventProc(short n,beEventProcPtr eventProc)
{
register tEasyWindow *thisWindow;
thisWindow = GoodWNum(n);
if(thisWindow)
thisWindow->wEventProc = eventProc;
}
long GetWindowFlags(short n)
{
tEasyWindow *thisWindow;
if(!(thisWindow = GoodWNum(n)))
return 0;
return thisWindow->flags;
}
void SetWindowFlags(short n,long flags)
{
tEasyWindow *thisWindow;
if(!(thisWindow = GoodWNum(n)))
return;
thisWindow->flags = flags;
}
void SetAbout(StringPtr progName,StringPtr s0,beAboutProcPtr aboutProc)
/*
* Sets the program's name in the about box, and
* sets the second string as ParamText 0 (^0)
* for the about dialog, 1962.
*/
{
short i;
SetItem(gMenuHandleList[1],1,(StringPtr)progName);
for(i=0; i<256; i++)
gAboutS0[i] = *s0++;
gAboutProc = aboutProc;
}
/************************************
* Error Handling
************************************/
void InstallMyExitToShell(void)
/*
* Add my HatStrap call to
* the classic routine, "ExitToShell"
*/
{
gOldExitToShell = (void *) NGetTrapAddress(trapExitToShell, ToolTrap);
NSetTrapAddress((long) MyExitToShell, trapExitToShell, ToolTrap);
}
pascal void MyExitToShell(void)
/*
* My exit routine, which does
* all the good cleanup.
*/
{
Hatstrap();
NSetTrapAddress((long) gOldExitToShell, trapExitToShell, ToolTrap);
ExitToShell();
}
void FailNil(long x)
/*
* If x is zero, post an error
* alert and quit the program.
*/
{
if(!x)
{
Alert(200,nil);
Debugger();
ExitToShell();
}
}
void FailOSErr(long x)
/*
* If x isn't zero, post an error
* alert and quit the program.
*/
{
if(x)
{
Debugger();
Alert(200,nil);
ExitToShell();
}
}
/************************************
* Some inherent methods
************************************/
void BEUndo(short n)
{
if(!SystemEdit(0))
(*gAppUndoProc)(n);
}
void BECut(short n)
{
if(!SystemEdit(2))
(*gAppCutProc)(n);
}
void BECopy(short n)
{
if(!SystemEdit(3))
(*gAppCopyProc)(n);
}
void BEPaste(short n)
{
if(!SystemEdit(4))
(*gAppPasteProc)(n);
}
void BEClear(short n)
{
if(!SystemEdit(5))
(*gAppClearProc)(n);
}
void BENull(void){}
/************************************
* Menu Action Routines
************************************/
Boolean DoKeyPress(long k)
{
register long thePoint;
register Boolean didIt;
thePoint = MenuKey((char)k);
didIt = (thePoint>>16) != 0;
if(didIt)
MenuPoint(thePoint);
return didIt;
}
void MenuClick(Point p)
{
KeyMap theKeys;
Boolean putBack = false;
short oldID;
if (phantomMenuH) {
#if THINK_C < 5
GetKeys( &theKeys );
#else
GetKeys(theKeys);
#endif
if ((theKeys[1]&4) == 0) {
putBack = true;
oldID = (**phantomMenuH).menuID;
DeleteMenu( oldID );
}
}
MenuPoint(MenuSelect(p));
if (putBack)
{
InsertMenu(phantomMenuH,oldID);
}
}
void MenuPoint(long theclick)
{
register short mID,mItem;
char DAname[30];
short wNum;
tEasyWindow *thisWindow;
register beMenuProcPtr aProc;
register tEasyMenuItem *emi;
mID = theclick>>16;
mItem = theclick & 0xffff;
if(mID == 0) return;
if(mID == 1) /* Apple menu */
{
if(mItem == 1) /* Its either the about box */
DoMyAbout();
else
{ /* Or a DA */
GetItem(gMenuHandleList[1],mItem,(StringPtr)DAname);
OpenDeskAcc((StringPtr)DAname);
}
}
else
{
wNum = gLastFrontWindowNumber;
thisWindow = GoodWNum(wNum);
if(thisWindow) /* if one of our window in front, setport */
SetPort(thisWindow->wWindow);
emi = &gMenu[mID][0];
aProc = emi->proc;
if(aProc) /* call the menu's routine, if any */
(*aProc)(wNum,mItem,gMenu[mID][mItem].ref);
emi = &gMenu[mID][mItem];
aProc = emi->proc;
if(aProc) /* call the item's routine, if any */
(*aProc)(wNum,mItem,emi->ref);
}
HiliteMenu(0);
}
char dAbout[] = "\pAbout ";
void StartMenus(void)
/*
* Start with just an About box, and some DA's.
*/
{
char aboutS[255];
MenuHandle applemenu;
BlockMove(&dAbout[0],aboutS,dAbout[0]+1); /* "About" */
BlockMove((StringPtr )0x910 + 1,aboutS + aboutS[0] + 1, *(StringPtr )0x910); /* ProgName */
aboutS[0] += *((StringPtr )0x910);
aboutS[aboutS[0] + 1] = '…';
aboutS[0]++;
applemenu = NewMenu(1,(StringPtr)"\p"); /* Apple menu: ID 1 */
AppendMenu(applemenu,(StringPtr)aboutS);
AppendMenu(applemenu,(StringPtr)"\p(-");
AddResMenu(applemenu,'DRVR');
InsertMenu(applemenu,0);
DrawMenuBar();
gMenuHandleList[1] = applemenu;
gMenuCount = 1; /* Next menu added will be ID 2 */
gCurrentMenu = 1;
gMenuLength[1] = 0; /* No items, really, in Apple menu */
}
MenuHandle InstallMenu(StringPtr s,beMenuProcPtr action,short ref)
/*
* Start a new menu with name s
*/
{
register tEasyMenuItem *emi;
register MenuHandle mh;
gMenuCount++; /* new menu */
gCurrentMenu = gMenuCount;
if(*s > kMenuNameMax-1)
*s = kMenuNameMax-1;
gMenuLength[gCurrentMenu] = 0;
mh = NewMenu(gCurrentMenu,(StringPtr)s);
gMenuHandleList[gCurrentMenu] = mh;
InsertMenu(mh,0);
if(ref < 0)
{
DisableItem(mh,0);
ref =- ref;
}
emi = &gMenu[gCurrentMenu][0];
emi->proc = action;
emi->ref = ref;
gInvalidMenuBar = true; /* redraw soon */
BlockMove(s,gMenuName[gCurrentMenu],*s+1);
return mh;
}
void InstallMenuItem(StringPtr s,beMenuProcPtr action,short ref)
/*
* Add an item to the last menu, and associate a routine with it.
*/
{
register MenuHandle mh;
register tEasyMenuItem *emi;
register short item;
mh = gMenuHandleList[gCurrentMenu];
gMenuLength[gCurrentMenu]++;
item = gMenuLength[gCurrentMenu];
emi = &gMenu[gCurrentMenu][item];
if (ref < 0)
{
DisableItem(mh,item);
ref =- ref;
emi->enable = 0;
}
else
emi->enable = 1;
AppendMenu(mh,(StringPtr)s);
emi->proc = action;
emi->ref = ref;
emi->mark = 0;
if(*(s+*s-1) == '/')
emi->cmdEquiv = *(s+*s);
else
emi->cmdEquiv = 0;
}
void DeleteMenuItem(short ref)
/*
* Remove all menu items with
* refcon ref.
*/
{
short menu;
short item;
for(menu = 1; menu <= gMenuCount; menu++)
for(item = gMenuLength[menu]; item > 0; item--)
{
if(gMenu[menu][item].ref == ref)
DeleteIndexedMenuItem(menu,item);
}
}
void DeleteIndexedMenuItem(short menu,short item)
{
StringPtr oldStrings;
MenuHandle mh;
short i;
short itemCount;
register tEasyMenuItem *emi;
register StringPtr w;
itemCount = gMenuLength[menu];
mh = gMenuHandleList[menu];
oldStrings = (StringPtr)NewPtr(256 * (itemCount));
FailNil((long)oldStrings);
for(i = 1; i<=itemCount; i++)
GetItem(mh,i,(StringPtr)&oldStrings[(i-1)*256]);
DeleteMenu(menu);
DisposeMenu(mh);
mh = NewMenu(menu,(StringPtr)gMenuName[menu]);
emi = &gMenu[menu][1];
w = oldStrings;
for(i = 1; i<=itemCount; i++)
{
if(i != item)
{
if(emi->cmdEquiv)
{
*(w+*w+1) = '/';
*(w+*w+2) = emi->cmdEquiv;
*w = *w + 2;
}
AppendMenu(mh,(StringPtr)w);
}
emi++;
w += 256;
}
emi = &gMenu[menu][item];
for(i = item; i<itemCount; i++)
{
*emi = *(emi+1);
emi++;
}
gMenuLength[menu]--;
itemCount--;
emi = &gMenu[menu][1];
for(i = 1; i<=itemCount; i++)
{
if(!emi->enable)
DisableItem(mh,i);
if(emi->mark)
SetItemMark(mh,i,emi->mark);
emi++;
}
InsertMenu(mh,menu+1);
DisposPtr((Ptr)oldStrings);
}
void InstallEditMenu(Xundo,Xcut,Xcopy,Xpaste,Xclear)
/*
* Start an edit menu, and put the first six things in.
*/
beWNumCallProcPtr Xundo,Xcut,Xcopy,Xpaste,Xclear;
{
gAppUndoProc = Xundo;
gAppCutProc = Xcut;
gAppCopyProc = Xcopy;
gAppPasteProc = Xpaste;
gAppClearProc = Xclear;
InstallMenu((StringPtr )"\pEdit",nil,0);
InstallMenuItem((StringPtr )"\px/Z",(beMenuProcPtr)BEUndo,-mUndo); /* barfs because it is static */
InstallMenuItem((StringPtr )"\p(-",(beMenuProcPtr)BENull,0);
InstallMenuItem((StringPtr )"\px/X",(beMenuProcPtr)BECut,-mCut);
InstallMenuItem((StringPtr )"\px/C",(beMenuProcPtr)BECopy,-mCopy);
InstallMenuItem((StringPtr )"\px/V",(beMenuProcPtr)BEPaste,-mPaste);
InstallMenuItem((StringPtr )"\px/B",(beMenuProcPtr)BEClear,-mClear);
gMenuEdit = gMenuHandleList[gCurrentMenu];
EnDisEdits(-1,-1,-1,-1,-1);
}
void SetMenuItem(short ref,char enable,char isMarked,char mark,StringPtr s)
/*
* Set all items with the reference number to the
* enable/disable state, with mark, and name s.
* pass enable + to enable, - to disable, and
* zero to leave alone.
*/
{
short m,i;
MenuHandle mh;
register tEasyMenuItem *emi;
for(m=1; m<=gMenuCount; m++)
{
mh = gMenuHandleList[m];
for(i=gMenuLength[m]; i>=0; i--)
{
emi = &gMenu[m][i];
if(emi->ref == ref)
{
if(enable)
{
if(!i)
gInvalidMenuBar = true;
if(enable > 0)
{
emi->enable = 1;
EnableItem(mh,i);
}
else
{
emi->enable = 0;
DisableItem(mh,i);
}
}
if(i > 0) /* these only apply to items */
{
if(isMarked)
if(isMarked > 0)
{
emi->mark = mark;
SetItemMark(mh,i,mark);
}
else
{
emi->mark = 0;
SetItemMark(mh,i,0);
}
if(s)
SetItem(mh,i,(StringPtr)s);
}
}
}
}
}
void EnDisEdits(short Eundo,short Ecut,short Ecopy,short Epaste,short Eclear)
/*
* For each edit menu entry,
* -1=disable, 1=enable, 0=leave alone.
*/
{
SetMenuItem(mUndo,Eundo,false,0,(StringPtr )"\pUndo");
SetMenuItem(mCut,Ecut,false,0,(StringPtr )"\pCut");
SetMenuItem(mCopy,Ecopy,false,0,(StringPtr )"\pCopy");
SetMenuItem(mPaste,Epaste,false,0,(StringPtr )"\pPaste");
SetMenuItem(mClear,Eclear,false,0,(StringPtr )"\pClear");
}
void SetCurrentMenu(short ref)
/*
* Set which menu will take
* future "InstallMenuItem"s.
*/
{
register short i;
for(i = 0; i<gMenuCount; i++)
{
if(gMenu[i][0].ref == ref)
gCurrentMenu = i;
}
}
short ScanWindowList(WindowPtr w)
/*
* return a window number from a WindowPeek,
* or -1 if no known window.
*/
{
short i;
tEasyWindow *wo;
wo= &gEasyWindowList[0];
for(i=0; i<gEasyWindowListSize; i++)
{
if (wo->wUsed && (wo->wWindow==w))
return i;
wo++;
}
return -1;
}
/************************************
Mouse Action Routines
************************************/
void DoMouseClick(EventRecord *event)
{
WindowPtr w;
short part;
register short wNum;
short i;
register tEasyWindow *thisEasyWindow;
Point p;
Rect r;
boolean tookEvent;
p = event->where;
part = FindWindow (p, &w);
wNum = ScanWindowList(w);
thisEasyWindow = GoodWNum(wNum);
switch (part)
{
case inDesk:
break;
case inMenuBar:
MenuClick(p);
break;
case inSysWindow:
SystemClick(event,w);
break;
case inContent:
contentClick:
if (w != FrontWindow()) /* If clicked on a non-front window, */
SelectWindow(w); /* bring it to the front. */
else if(thisEasyWindow) /* Click on front window: give click */
{ /* to window's click routine. */
SetPort(w);
GlobalToLocal(&p);
ClipRect(&gBigRect);
SetOrigin(0,0);
if(thisEasyWindow && thisEasyWindow->wEventProc)
(*thisEasyWindow->wEventProc)(wNum,event,&tookEvent);
else
tookEvent = false;
if(!tookEvent)
{
register beClickProcPtr fp;
fp = thisEasyWindow->wClickProc;
if(fp)
(*fp)(wNum,p,
event->modifiers);
}
}
break;
case inDrag:
if(((thisEasyWindow->flags & wCoolDrag)!=0) ^ ((event->modifiers & optionKey)!=0))
{
gCoolDragPoint = event->where;
gCoolDragState = 1;
gCoolDragWindow = w;
if(!(event->modifiers & 256))
SelectWindow(w);
}
else
if(Button()) /* so quick title-bar clix */
DragWindow(w,event->where,&gBigRect); /* still work */
else
SelectWindow(w);
break;
case inGrow:
if(thisEasyWindow && (thisEasyWindow->flags & wGrowable))
{
long oldSize,newSize;
beGrowWindowProcPtr fp;
beResizeProcPtr rsfp;
SetPort(w);
GetGrowRect(w,&r);
InvalRect(&r);
fp = thisEasyWindow->wGrowWindowProc;
if(fp)
(*fp)(&newSize,wNum,w,event->where,&gResizeLim);
else
newSize = GrowWindow(w,event->where,&gResizeLim);
rsfp = thisEasyWindow->wResizeProc;
if(rsfp)
{
oldSize = ((long)(w->portRect.bottom-w->portRect.top)<<16) |
(w->portRect.right-w->portRect.left);
(*rsfp)(wNum,(Point *)&oldSize,(Point *)&newSize,event->modifiers);
}
else
SizeWindow(w,newSize&0xffff,newSize>>16,1);
GetGrowRect(w,&r);
InvalRect(&r);
}
else
goto contentClick;
break;
case inGoAway:
if(thisEasyWindow)
if (TrackGoAway(w,event->where))
{
beGoAwayProcPtr fp;
fp = thisEasyWindow->wGoAwayProc;
if(fp)
(*fp)(wNum);
}
break;
/*
* The following way to handle zoom only
* applies to zooming to 1 state. This does
* not handle zooming in and out between 2
* states. Check IM IV.
*/
case inZoomIn: /* zoomBox */
case inZoomOut:
if(thisEasyWindow)
{
if (TrackBox(w,event->where,part))
{
beZoomProcPtr fp;
fp = thisEasyWindow->wZoomProc;
if(fp)
(*fp)(wNum);
}
}
break;
}
}
/************************************
Window Action Routines
************************************/
WindowPtr InstallWindow(short iNum,StringPtr iTitle,Rect *iRect,short iType,short iFlags,
beUpdateProcPtr iUpdate,beClickProcPtr iClick,beKeyProcPtr iKey,beGoAwayProcPtr iGoAway,
beActivateProcPtr iActivate,beDeactivateProcPtr iDeactivate,beIdleProcPtr iIdle)
/*
* Add a window to BigEasy's list. If the window is
* already up somewhere, bring it to the front and
* visualize it.
*/
{
tEasyWindow *thisWindow;
Rect stagRect,**oldPos;
boolean isVisible;
RgnHandle rh;
KeyMap km;
boolean opt;
#if THINK_C < 5
GetKeys(&km);
#else
GetKeys(km);
#endif
opt =km[58/8] & (1<< (58%8) );
isVisible = iNum>0;
if(!isVisible)
iNum = -iNum;
EnoughEasyWindows(iNum); /* Make sure there's space for new one */
thisWindow = &gEasyWindowList[iNum];
if (thisWindow->wUsed) /* something already assigned to this window? */
{
Show(iNum);
goto goHome;
}
oldPos = (Rect **)Get1Resource(kWinPosType,iNum); /* attempt to find saved window position */
rh = NewRgn();
if(oldPos && !opt) /* (option key "forgets" old window spot */
RectRgn(rh,*oldPos);
SectRgn(rh,*(RgnHandle *)0x9EE,rh);
if(!EmptyRgn(rh)) /* is save spot on the desktop? */
{
stagRect = **oldPos;
isVisible = stagRect.left < stagRect.right; /* swap left and right for invisible */
if(!isVisible)
SwapShort(stagRect.left,stagRect.right);
}
else
{
stagRect = *iRect;
if(gStaggerWindows)
{
gStagX = (gStagX + kStagStepX)%kStagLimX;
gStagY = (gStagY + kStagStepY)%kStagLimY;
OffsetRect(&stagRect,gStagX,gStagY);
}
}
DisposeRgn(rh);
thisWindow->wUsed = 1;
thisWindow->wWindow = NewCWindow(0,&stagRect,(StringPtr)iTitle,isVisible,
((iFlags & wZoomable) != 0) ? zoomDocProc : iType,
(WindowPtr)-1,iGoAway!=0,0);
SetPort(thisWindow->wWindow);
thisWindow->flags = iFlags;
thisWindow->wUpdateProc = iUpdate;
thisWindow->wClickProc = iClick;
thisWindow->wKeyProc = iKey;
thisWindow->wGoAwayProc = iGoAway;
thisWindow->wZoomProc = nil;
thisWindow->wActivateProc = iActivate;
thisWindow->wDeactivateProc = iDeactivate;
thisWindow->wIdleProc = iIdle;
thisWindow->wResizeProc = nil;
thisWindow->wGrowWindowProc = nil;
thisWindow->wEventProc = nil;
goHome:
return thisWindow->wWindow;
}
void UninstallWindow(short iNum)
{
register tEasyWindow *thisWindow;
register beDeactivateProcPtr fp;
gCoolDragState = 0; /* just in case we were dragging the dissappeared window */
if(!(thisWindow = GoodWNum(iNum)))
return;
fp = thisWindow->wDeactivateProc;
if(fp)
(*fp)(iNum);
CloseWindow(thisWindow->wWindow);
thisWindow->wUsed = 0;
}
void Show(short iNum)
{
register tEasyWindow *thisWindow;
thisWindow = GoodWNum(iNum);
if(thisWindow)
{
if(!((WindowPeek)(thisWindow->wWindow))->visible) /* If so, just show it, and bring it to the front. */
ShowWindow(thisWindow->wWindow);
SelectWindow(thisWindow->wWindow);
}
}
void Hide(short iNum)
/*
* Just do HideWindow to the
* specified window number.
*/
{
register tEasyWindow *thisWindow;
gCoolDragState = 0; /* It might have been this window */
thisWindow = GoodWNum(iNum);
if(thisWindow)
HideWindow(thisWindow->wWindow);
}
void GetWindowRect(short n,Rect *r)
/*
* return the window's current rectangle
* in global coördinate space.
*/
{
tEasyWindow *thisWindow;
WindowPtr g;
if(!(thisWindow = GoodWNum(n)))
return;
if(thisWindow->wUsed)
{
g = thisWindow->wWindow;
SetPort(g);
*r = g->portRect;
LocalToGlobal((Point *)r);
LocalToGlobal((Point *)( (char*)r + 4));
}
}
WindowPtr GetWindowPtr(short n)
/*
* return the windowptr for
* the specified window number
*/
{
tEasyWindow *thisWindow;
WindowPtr g;
if(!(thisWindow = GoodWNum(n)))
g = 0;
else
g = thisWindow->wWindow;
return g;
}
boolean GetWindowVisible(short n)
/*
* return true if the window exists,
* and is visible, or false if its invisible
* or doesn't exist.
*/
{
register WindowPtr g;
g = GetWindowPtr(n);
if(g)
return ((WindowPeek)g)->visible;
else
return false;
}
void SaveWindowPosition(short n)
/*
* Save the position of window number n,
* or all windows if n = -1;
*/
{
Rect **rH;
register Rect *r;
register short i;
register short n1,n2;
tEasyWindow *thisWindow;
rH = (Rect **)NewHandle(sizeof(Rect));
FailNil((long)rH);
HLock((Handle)rH);
r = *rH;
if(n < 0)
{
n1 = 0;
n2 = gEasyWindowListSize-1;
}
else
n1 = n2 = n;
for(i = n1; i<=n2; i++)
{
thisWindow = GoodWNum(i);
if(thisWindow && thisWindow->wUsed)
{
GetWindowRect(i,r);
if( !((WindowPeek)(thisWindow->wWindow))->visible )
SwapShort(r->left,r->right);
Replace1Resource((Handle)rH,kWinPosType,i);
}
}
DisposHandle( (Handle)rH );
}
void ForgetWindowPosition(short n)
/*
* Forget the saved window position n,
* or all windows if n<0.
*/
{
register short i;
register short n1,n2;
register tEasyWindow *thisWindow;
if(n < 0)
{
n1 = 0;
n2 = gEasyWindowListSize-1;
}
else
n1 = n2 = n;
for(i = n1; i<=n2; i++)
{
thisWindow = GoodWNum(i);
if(thisWindow && thisWindow->wUsed)
Replace1Resource(0,kWinPosType,i);
}
}
void Replace1Resource(Handle h,long type,short id)
/*
* This is AddResource with a
* RmveResource if necessary.
* Pass h==nil to delete the resource.
*/
{
Handle old;
/*
* A lame hack to prevent writing resources
* to a lightspeed project file.
*/
if( *(StringPtr)(0x910 + (*(StringPtr)0x910)) == 'π')
{
/* do nothing */
}
else
{
old = Get1Resource(type,id);
if(old)
RmveResource(old);
if(h)
{
AddResource(h,type,id,(StringPtr)"\p");
WriteResource(h);
DetachResource(h);
}
}
}
void CheckMenubar(void)
{
if(gInvalidMenuBar)
{
DrawMenuBar();
gInvalidMenuBar = false;
}
}
/************************************
* Event Routines
************************************/
void EventLoop(void)
{
EventRecord er;
short i;
register short wNum;
WindowPtr w;
register tEasyWindow *thisEasyWindow;
Boolean tookKey,tookEvent;
Rect r;
CheckMenubar();
WaitNextEvent(0xffff,&er,gSleep,nil);
{
gLastModifiers = er.modifiers;
if(er.what > 5 && er.what < 12) /* update event or higher: in message */
w = (WindowPtr)er.message;
else
w = FrontWindow(); /* else, use FrontW */
if(er.what > 1)
{
wNum = ScanWindowList(w); /* other than null or click, scan list */
thisEasyWindow = GoodWNum(wNum); /* and get record */
}
else
thisEasyWindow = 0;
SetPort(w);
if(thisEasyWindow && thisEasyWindow->wEventProc)
(*thisEasyWindow->wEventProc)(wNum,&er,&tookEvent);
else
tookEvent = 0;
if(!tookEvent)
switch (er.what)
{
case 0: /* null event */
break;
case mouseDown:
FrontDAEdits();
DoMouseClick(&er);
break;
case keyDown:
case autoKey:
FrontDAEdits();
tookKey = false;
if( (!gMenuNeedsCmdKey) || (er.modifiers & 256) )
tookKey = DoKeyPress(er.message);
if(!tookKey && ((!gMenuNeedsCmdKey) || (er.modifiers & 256)) )
tookKey = CoolBigEasyCmdKeys(er.message & 0xFF);
if(!tookKey)
if(thisEasyWindow)
{
beKeyProcPtr fp;
fp = thisEasyWindow->wKeyProc;
if(fp)
{
SetPort(thisEasyWindow->wWindow); /* Set port to window */
(*fp)(wNum, /* Call key proc */
(short)(er.message&0xff), /* with the key */
(short)((er.message>>8)&0xff), /* the key code */
er.modifiers); /* and the modifiers */
}
}
break;
case updateEvt:
if(thisEasyWindow)
{
Rect visBounds,dummyRect;
beUpdateProcPtr fp;
BeginUpdate(w);
visBounds = (**w->visRgn).rgnBBox;
fp = thisEasyWindow->wUpdateProc;
if(fp)
{
SetPort(thisEasyWindow->wWindow); /* Set port to window */
(*fp)(wNum); /* Call drawing proc */
}
SetOrigin(0,0);
if (thisEasyWindow->flags & wGrowable) /* Draw growbox, if... */
MyDrawGrowIcon(w);
ClipRect(&gBigRect);
EndUpdate((WindowPtr)er.message);
}
break;
case activateEvt:
FrontDAEdits();
if(thisEasyWindow)
{
EnDisEdits(-1,-1,-1,-1,-1);
if(er.modifiers & 1)
{
activateMe:
{
beActivateProcPtr fp;
fp = thisEasyWindow->wActivateProc;
if(fp)
(*fp)(wNum);
}
}
else
{
deactivateMe:
{
beDeactivateProcPtr fp;
fp = thisEasyWindow->wDeactivateProc;
if(fp)
(*fp)(wNum);
}
}
InitCursor();
if (thisEasyWindow->flags & wGrowable) /* Draw growbox, if... */
MyDrawGrowIcon(w);
}
break;
case kOSEvent:
switch ((unsigned long) er.message >> 24) /* high byte of message */
{
case kSuspendResumeMessage:
if(thisEasyWindow) /* just like activate event... */
{
EnDisEdits(-1,-1,-1,-1,-1);
if(er.message & kResumeMask)
goto activateMe;
else
goto deactivateMe;
}
break;
}
break;
case kHighLevelEvent:
AEProcessAppleEvent(&er);
break;
default:
/*Debugger();/**/
;
}
}
/*
* See if we're doing a fake cool drag-window
*/
if(gCoolDragState)
{
Point p,q;
SetPort(gCoolDragWindow);
GetMouse(&p);
LocalToGlobal(&p);
if( (p.v!=gCoolDragPoint.v) || (p.h!=gCoolDragPoint.h) )
{
q.h = gCoolDragWindow->portRect.left;
q.v = gCoolDragWindow->portRect.top;
LocalToGlobal(&q);
MoveWindow(gCoolDragWindow,
q.h+p.h-gCoolDragPoint.h,
q.v+p.v-gCoolDragPoint.v,0);
gCoolDragPoint = p;
}
if(!Button())
gCoolDragState = 0;
}
SystemTask();
w = FrontWindow();
if ( w == gLastFrontIdle) /* Minor optimization, wins if the same */
wNum = gLastFrontWindowNumber; /* window is frontmost for a while. */
else
{
wNum = ScanWindowList(w);
gLastFrontIdle = w;
gLastFrontWindowNumber = wNum;
}
if(er.what != mouseDown && er.what != activateEvt) /* anything but a mousedown or [de]activate */
for(i = 1; i<gEasyWindowListSize; i++)
{
if(gEasyWindowList[i].wUsed && gEasyWindowList[i].wIdleProc)
{
SetPort(gEasyWindowList[i].wWindow);
(*gEasyWindowList[i].wIdleProc)((short)i,(boolean)(w == gEasyWindowList[i].wWindow));
}
}
if (gMasterIdleProc)
(*gMasterIdleProc)();
}
Boolean CoolBigEasyCmdKeys(short key)
{
WindowRecord *w;
switch(key)
{
/*
* Rotate active window
*/
case 9: /* <tab> */
w = *(WindowRecord **)0x9D6; /* windowlist */
if(w)
{
while (w->nextWindow)
w = w->nextWindow;
SelectWindow((WindowPtr)w);
}
break;
default:
return false;
}
return true;
}
void IdleWindow(short n)
/*
* Idle window number n, or
* -1 to idle all windows.
*/
{
register short i;
short lo,hi;
WindowPtr w;
register tEasyWindow *ew;
if(n<0)
{
lo = 1;
hi = gEasyWindowListSize;
}
else
{
lo = n;
hi = n + 1;
}
w = FrontWindow();
ew = &gEasyWindowList[lo];
for(i = lo; i < hi; i++)
{
if(ew->wUsed && ew->wIdleProc)
(*ew->wIdleProc)((short)i,ew->wWindow == w);
ew++;
}
SystemTask();
}
void MyDrawGrowIcon(WindowPtr w)
{
Rect r;
SetPort(w);
GetGrowRect(w,&r);
ClipRect(&r);
DrawGrowIcon(w);
ClipRect(&gBigRect);
}
void SetMasterOpenAppMessage(EventHandlerProcPtr openAppProc)
{
if(gHasAppleEvents)
AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
openAppProc, 0, false);
}
void SetMasterOpenDocMessage(EventHandlerProcPtr openDocProc)
{
if(gHasAppleEvents)
AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
openDocProc, 0, false);
}
void InitBigEasy(void)
{
long result;
InstallMyExitToShell();
gMasterIdleProc = nil;
gAboutProc = nil;
gQuitApp = false;
gMenuNeedsCmdKey = true;
gStaggerWindows = true;
gSleep = 0;
gInvalidMenuBar = false;
SetRect(&gBigRect,-16000,-16000,16000,16000);
gEasyWindowListH = (tEasyWindow**)NewHandle(sizeof(tEasyWindow));
HLock((Handle)gEasyWindowListH);
gEasyWindowList = *gEasyWindowListH;
gEasyWindowList[0].wUsed = 0;
gEasyWindowListSize = 1;
gLastFrontIdle = (WindowPtr) 0;
gLastFrontWindowNumber = -1;
gCoolDragState = 0;
/*
* 7.0 Feature stuff
*/
gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &result) ? false : result != 0);
}
void main(void)
{
#if 0
#ifdef THINK_C_PROFILE
freopen("profile output","w+",stdout);
InitProfile(1000,50);
#endif THINK_C_PROFILE
#endif
MaxApplZone();
MoreMasters();
MoreMasters();
InitToolbox();
StartMenus();
InitBigEasy();
Bootstrap();
#if THINK_C >= 5
#if defined(STACK_KILLER) || defined(TIMING_PROFILE)
prepStackKiller(); /** slime from HELL **/
#ifdef TIMING_PROFILE
InitTimingProfile(150); /* call depth */
#endif TIMING_PROFILE
#endif
#endif
while (!gQuitApp)
EventLoop();
FlushEvents(0xffff,0);
#ifdef TIMING_PROFILE
DumpProfile(0, 0, "\ptiming stats");
#endif
ExitToShell();
}